package com.dz.lm.common.util;

import com.smartlbs.util.*;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipOutputStream;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.*;

public class FileUpOrDownUtil {
    /**
     * 定义上传文件的方法
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    public Map<String,Object> fileUp(HttpServletRequest request,
                                     HttpServletResponse response) throws Exception {
        //上传文件最大值M
        //final long FILE_MAX_SIZE=1*1024*1024;
        boolean isMultipart = ServletFileUpload.isMultipartContent(request);
        //存放所有的普通表单字段值
        Map formFieldMap=new HashMap();
        //处理多文件上传的问题
        List list=new LinkedList();
        int ifSu=0;//判断是否有异常，0为没有，1表示有异常
        //将所有的结果集存放map
        Map<String,Object> map=new HashMap<String,Object>();
        map.put("ifSu", ifSu);

        if(isMultipart){
            DiskFileItemFactory factory=new DiskFileItemFactory();
            //如果文件小于5M,直接上传
            factory.setSizeThreshold(5*1024*1024);
            /**
             * 如果大于5M,通过缓冲区上传
             */
            //获取缓冲区路径
            String buffer=request.getRealPath("/upload");
            //为工厂指定缓冲路径
            factory.setRepository(new File(buffer));

            //根据浏览器判断解码类型
            String encoding="";
            if(UserAgentUtil.isIE(request)){
                encoding="GBK";
            }else{
                encoding="UTF-8";
            }

            ServletFileUpload upload = new ServletFileUpload(factory);
            upload.setHeaderEncoding(encoding);
            //upload.setSizeMax(FILE_MAX_SIZE);
            List<FileItem> fileItem=new ArrayList<FileItem>();
            try {
                fileItem = upload.parseRequest(request);

                Iterator<FileItem> iterator = fileItem.iterator();
                while(iterator.hasNext()){
                    FileItem item = (FileItem) iterator.next();
                    //如果是普通表单域，则将字段及字段值存入map
                    if(item.isFormField()){
                        String fieldName=item.getFieldName();

                        String value = item.getString(encoding);
                        formFieldMap.put(fieldName, value);

                        if(!StringUtil.containEmpty(value)){
                            if(value.startsWith("data:image") && value.indexOf(";base64,") > -1){
                                String[] typeAndValue = value.split(";base64,");
                                String base64 = typeAndValue[1];
                                String suffix = typeAndValue[0].split("/")[1];

                                String name = Base64Img.getUUid()+"."+suffix;
                                //byte[] bytes = Base64Img.getBytes(base64);
                                byte[] bytes = Base64.decodeBase64(base64);
                                UploadFile fileVo = new UploadFile();
                                fileVo.setFile_bytes(bytes);
                                fileVo.setFile_name(name);
                                fileVo.setFile_size(bytes.length);
                                fileVo.setField_name(fieldName);
                                list.add(fileVo);

                                formFieldMap.remove(fieldName);
                            }
                        }


                    }else{
                        //如果是文件域，刚将多个文件上传并存放到数组中
                        if(!StringUtil.containEmpty(item.getName())){
                            UploadFile fileVo = new UploadFile();
                            fileVo.setFile_bytes(item.get());
                            fileVo.setFile_name(item.getName());
                            fileVo.setFile_size(item.getSize());
                            fileVo.setField_name(item.getFieldName());
                            list.add(fileVo);
                        }
                    }
                }
                map.put("formField", formFieldMap);
                map.put("fileField", list);
                map.put("ifSu", 0);
            } catch (Exception e) {
                e.printStackTrace();
                ifSu=1;//表示文件(图片)过大，需重新上传文件
                map.put("ifSu", ifSu);

            }
        }else{
            Map<String,Object> dto = new HashMap<String,Object>();
            Map mapParam = request.getParameterMap();
            Set<Map.Entry<String, String[]>> entrySet = mapParam.entrySet();
            for(Map.Entry<String, String[]> entry:entrySet){
                String[] strArr = entry.getValue();
                if(strArr.length == 1){
                    dto.put(entry.getKey(), strArr[0]);
                }else{
                    dto.put(entry.getKey(), strArr);
                }
            }
            map.put("formField", dto);
            map.put("fileField", null);
            map.put("ifSu", 0);
        }
        return map;

    }

    /**
     * 下载文件
     * @param response
     * @param filePath
     * @param fileRealName

     */
    public static void download(HttpServletResponse response,String filePath,String fileRealName){
        File file=new File(filePath);
        if(file.exists()){
            //取得文件类型
            String fileName = file.getName();
            int index = fileName.lastIndexOf(".")+1;
            String fileExt = "";
            if(index>0){
                fileExt = fileName.substring(index);
            }
            String fileType=getFileTypeValue(fileExt);

            //读取
            try {
                FileInputStream fin = new FileInputStream(file);

                byte a[]=new byte[1024*100];
                OutputStream outs=response.getOutputStream();

                response.setHeader("Content-Disposition","attachment; filename="+ new String( fileRealName.getBytes("gbk"), "ISO8859-1"));
                response.setContentType(fileType);
                response.setHeader("Content_Length",String.valueOf(fin.available()));
                response.setContentLength(fin.available());

                int read=0;
                while((read=fin.read(a))!=-1){
                    outs.write(a,0,read);
                }
                outs.close();
                fin.close();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                response.setStatus(500);
            }
        }else{
            response.setStatus(404);
        }
    }

    /**
     * 保存"下载附件"文件所对应的类型(map)
     * @return
     */
    public Map<String, String> getFileTypeMap(){
        Map<String, String> map=new HashMap<String, String>();
        map.put("ez","application/andrew-inset");
        map.put("hqx","application/mac-binhex40");
        map.put("cpt","application/mac-compactpro");
        map.put("doc","application/msword");
        map.put("bin","application/octet-stream");
        map.put("dms","application/octet-stream");
        map.put("lha","application/octet-stream");
        map.put("lzh","application/octet-stream");
        map.put("exe","application/octet-stream");
        map.put("class","application/octet-stream");
        map.put("so","application/octet-stream");
        map.put("dll","application/octet-stream");
        map.put("oda","application/oda");
        map.put("pdf","application/pdf");
        map.put("ai","application/postscript");
        map.put("eps","application/postscript");
        map.put("ps","application/postscript");
        map.put("smi","application/smil");
        map.put("smil","application/smil");
        map.put("mif","application/vnd.mif");
        map.put("xls","application/vnd.ms-excel");
        map.put("ppt","application/vnd.ms-powerpoint");
        map.put("wbxml","application/vnd.wap.wbxml");
        map.put("wmlc","application/vnd.wap.wmlc");
        map.put("wmlsc","application/vnd.wap.wmlscriptc");
        map.put("bcpio","application/x-bcpio");
        map.put("vcd","application/x-cdlink");
        map.put("pgn","application/x-chess-pgn");
        map.put("cpio","application/x-cpio");
        map.put("csh","application/x-csh");
        map.put("dcr","application/x-director");
        map.put("dir","application/x-director");
        map.put("dxr","application/x-director");
        map.put("dvi","application/x-dvi");
        map.put("spl","application/x-futuresplash");
        map.put("gtar","application/x-gtar");
        map.put("hdf","application/x-hdf");
        map.put("js","application/x-javascript");
        map.put("skp","application/x-koan");
        map.put("skd","application/x-koan");
        map.put("skt","application/x-koan");
        map.put("skm","application/x-koan");
        map.put("latex","application/x-latex");
        map.put("nc","application/x-netcdf");
        map.put("cdf","application/x-netcdf");
        map.put("sh","application/x-sh");
        map.put("shar","application/x-shar");
        map.put("swf","application/x-shockwave-flash");
        map.put("sit","application/x-stuffit");
        map.put("sv4cpio","application/x-sv4cpio");
        map.put("sv4crc","application/x-sv4crc");
        map.put("tar","application/x-tar");
        map.put("tcl","application/x-tcl");
        map.put("tex","application/x-tex");
        map.put("texinfo","application/x-texinfo");
        map.put("texi","application/x-texinfo");
        map.put("t","application/x-troff");
        map.put("tr","application/x-troff");
        map.put("roff","application/x-troff");
        map.put("man","application/x-troff-man");
        map.put("me","application/x-troff-me");
        map.put("ms","application/x-troff-ms");
        map.put("ustar","application/x-ustar");
        map.put("src","application/x-wais-source");
        map.put("xhtml","application/xhtml+xml");
        map.put("xht","application/xhtml+xml");
        //map.put("zip","application/zip");
        map.put("zip","application/x-zip-compressed");
        map.put("au","audio/basic");
        map.put("snd","audio/basic");
        map.put("mid","audio/midi");
        map.put("midi","audio/midi");
        map.put("kar","audio/midi");
        map.put("mpga","audio/mpeg");
        map.put("mp2","audio/mpeg");
        map.put("mp3","audio/mpeg");
        map.put("aif","audio/x-aiff");
        map.put("aiff","audio/x-aiff");
        map.put("aifc","audio/x-aiff");
        map.put("m3u","audio/x-mpegurl");
        map.put("ram","audio/x-pn-realaudio");
        map.put("rm","audio/x-pn-realaudio");
        map.put("rpm","audio/x-pn-realaudio-plugin");
        map.put("ra","audio/x-realaudio");
        map.put("wav","audio/x-wav");
        map.put("pdb","chemical/x-pdb");
        map.put("xyz","chemical/x-xyz");
        map.put("bmp","image/bmp");
        map.put("gif","image/gif");
        map.put("ief","image/ief");
        map.put("jpeg","image/jpeg");
        map.put("jpg","image/jpeg");
        map.put("jpe","image/jpeg");
        map.put("png","image/png");
        map.put("tiff","image/tiff");
        map.put("tif","image/tiff");
        map.put("djvu","image/vnd.djvu");
        map.put("djv","image/vnd.djvu");
        map.put("wbmp","image/vnd.wap.wbmp");
        map.put("ras","image/x-cmu-raster");
        map.put("pnm","image/x-portable-anymap");
        map.put("pbm","image/x-portable-bitmap");
        map.put("pgm","image/x-portable-graymap");
        map.put("ppm","image/x-portable-pixmap");
        map.put("rgb","image/x-rgb");
        map.put("xbm","image/x-xbitmap");
        map.put("xpm","image/x-xpixmap");
        map.put("xwd","image/x-xwindowdump");
        map.put("igs","model/iges");
        map.put("iges","model/iges");
        map.put("msh","model/mesh");
        map.put("mesh","model/mesh");
        map.put("silo","model/mesh");
        map.put("wrl","model/vrml");
        map.put("vrml","model/vrml");
        map.put("css","text/css");
        map.put("html","text/html");
        map.put("htm","text/html");
        map.put("asc","text/plain");
        map.put("txt","text/plain");
        map.put("rtx","text/richtext");
        map.put("rtf","text/rtf");
        map.put("sgml","text/sgml");
        map.put("sgm","text/sgml");
        map.put("tsv","text/tab-separated-values");
        map.put("wml","text/vnd.wap.wml");
        map.put("wmls","text/vnd.wap.wmlscript");
        map.put("etx","text/x-setext");
        map.put("xsl","text/xml");
        map.put("xml","text/xml");
        map.put("mpeg","video/mpeg");
        map.put("mpg","video/mpeg");
        map.put("mpe","video/mpeg");
        map.put("qt","video/quicktime");
        map.put("mov","video/quicktime");
        map.put("mxu","video/vnd.mpegurl");
        map.put("avi","video/x-msvideo");
        map.put("movie","video/x-sgi-movie");
        map.put("ice","x-conference/x-cooltalk");
        map.put("mp4", "video/mpeg4");
        return map;
    }

    /**
     * 根据文件后缀名匹配下载类型;eg:txt,jpg,avi;注：不带"."
     * @param fileExt：文件后缀名
     * @return
     */
    public static String getFileTypeValue(String fileExt){
        FileUpOrDownUtil fu=new FileUpOrDownUtil();
        Map<String, String> map=fu.getFileTypeMap();
        String fileType="";
        if(StringUtil.containEmpty(fileExt)){
            fileType="text/plain";
        }else{
            fileType=map.get(fileExt);
        }
        return fileType;
    }

    /**
     * 将传入文件列表压缩入zip中并下载
     * @param fileList
     * @param isDeleteFile		压缩包名称
     * 			Map:
     * 				file	文件
     * 				name	文件名
     * @param isDeleteFile  是否需要删除文件，导出excel时需要删除临时的excel，导出图片时不能删除图片
     */
    public static String downloadZips(List<Map> fileList,boolean isDeleteFile){
        //存入本地的zip
        File saveZipFile=new File(ConfigUtil.getProperty("file_temp_path")+(new Random().nextInt(10000))+"_"+System.currentTimeMillis()+".zip");
        try {
            //ZIP工作流
            ZipOutputStream zips = new ZipOutputStream(new FileOutputStream(saveZipFile));
            zips.setEncoding("GBK");

            if(fileList!=null && fileList.size()>0){
                for(Map map:fileList){
                    if(map.get("file")!=null && !map.get("file").toString().equals("")){
                        String filename=map.get("name").toString();
                        ZipEntry entry = new ZipEntry(filename);
                        zips.putNextEntry(entry);
                        //写入压缩包
                        //读文件
                        BufferedInputStream in = new BufferedInputStream(new FileInputStream(map.get("file").toString()));
                        //使用缓冲输出流包装，提升性能
                        BufferedOutputStream out = new BufferedOutputStream(zips);
                        int c;
                        while((c = in.read()) != -1){
                            out.write(c);
                        }
                        in.close();
                        out.flush();
                        zips.closeEntry();
                        //删除文件
                        if(isDeleteFile){
                            new File(map.get("file").toString()).delete();
                        }
                    }
                }
            }
            zips.close();

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return saveZipFile.getName();
    }

}
